#include "PacketCollector.h"

#include "PacketReader.h"
#include <filter/PacketFilter.h>
#include <packet/Packet.h>

PacketCollector::PacketCollector(PacketReader * packetReader, PacketFilter * packetFilter) : 
	packetReader(packetReader),
	packetFilter(packetFilter) 
{
}

void PacketCollector::cancel() {
	// If the packet collector has already been cancelled, do nothing.
	if (!cancelled) {
		cancelled = true;
		packetReader->cancelPacketCollector(this);
	}
}

Packet * PacketCollector::pollResult() {
	if (resultQueue.empty()) {
    	return NULL;
    } else {
		Packet * result = resultQueue.front(); 
		resultQueue.pop();
       	return result;
    }
}

Packet * PacketCollector::nextResult() { //TODO
    // Wait indefinitely until there is a result to return.
	boost::mutex::scoped_lock sl(mutex_read);
    while (resultQueue.empty()) {
        not_empty.wait(mutex_read);
    }
	Packet * result = resultQueue.front(); 
	resultQueue.pop();
    return result;
}

Packet * PacketCollector::nextResult(long timeout) {
    // Wait up to the specified amount of time for a result.
    if (resultQueue.empty()) {
		long waitTime = timeout;
		boost::system_time start = boost::get_system_time();
    	boost::system_time wait_until = start + boost::posix_time::milliseconds(timeout);
		boost::mutex::scoped_lock sl(mutex_read);
        // Keep waiting until the specified amount of time has elapsed, or
        // a packet is available to return.
        while (resultQueue.empty()) {
            not_empty.timed_wait(mutex_read, wait_until);
        }
        // Still haven't found a result, so return null.
        if (resultQueue.empty()) {
        	return NULL;
        }
    } 

	Packet * result = resultQueue.front(); 
	resultQueue.pop();
    return result;
    
}

void PacketCollector::processPacket(Packet * packet) {
    if (packet == NULL) {
    	return;
    }
    if (packetFilter == NULL|| packetFilter->accept(packet)) {
    	// If the max number of packets has been reached, remove the oldest one.
        if (resultQueue.size() == MAX_PACKETS) {
        	resultQueue.pop();
        }
        // Add the new packet.
        resultQueue.push(packet);
        // Notify waiting threads a result is available.
        not_empty.notify_all();//notifyAll();
	}
}
